<?php
namespace Org\Util;
use Think\Db;

class Access {
    //默认配置
    protected $_config = array(
        'AUTH_ON'           => true,                // 认证开关
        'AUTH_TYPE'         => 1,                   // 认证方式，1为实时认证；2为登录认证。
        'AUTH_USER'         => 'user',             // 用户信息表
        'AUTH_ACCESS'       => 'auth', //权限表
        'AUTH_ROLE'         => 'role', //角色表
        'AUTH_MENU'         => 'menu', //菜单表
        'AUTH_ADMIN_ROLE'   => 'admin_role', //用户角色表
        'AUTH_ROLE_AUTH'    => 'role_auth' //角色权限表
    );

    public function __construct() {
        $prefix = C('DB_PREFIX');
        $this->_config['AUTH_USER'] = $prefix.$this->_config['AUTH_USER'];
        $this->_config['AUTH_ACCESS'] = $prefix.$this->_config['AUTH_ACCESS'];
        $this->_config['AUTH_ROLE'] = $prefix.$this->_config['AUTH_ROLE'];
        $this->_config['AUTH_MENU'] = $prefix.$this->_config['AUTH_MENU'];
        $this->_config['AUTH_ADMIN_ROLE'] = $prefix.$this->_config['AUTH_ADMIN_ROLE'];
        $this->_config['AUTH_ROLE_AUTH'] = $prefix.$this->_config['AUTH_ROLE_AUTH'];
        if (C('AUTH_CONFIG')) {
            //可设置配置项 AUTH_CONFIG, 此配置项为数组。
            $this->_config = array_merge($this->_config, C('AUTH_CONFIG'));
        }
    }

    /**
      * 检查权限
      * @param uri string      模块名.'/'.控制器名.'/'.操作名
      * @param adminId  int       用户id
      * @return boolean           通过验证返回true;失败返回false
     */
    public function check($uri, $adminId) {
        if(!$this->_config['AUTH_ON'] || in_array($adminId, C('ADMINISTRATOR'))){
            return true;
        }

        //用户的权限
        $authList = $this->getAuthList($adminId);
        if (!$uri || empty($authList) || !count($authList)) {
            return false;
        }

        $uriItems = explode('/', $uri);
        foreach ($authList as $auth) {
            if ($uriItems[0] == $auth['module_name']
                && $uriItems[1] == $auth['controller_name']
                && $uriItems[2] == $auth['action_name'])
            {
                return true;
            }
        }

        return false;
    }

    /**
     * 根据用户id获取用户组,返回值为数组
     * @param  adminId int     用户id
     * @return array       用户所属的用户组 array(
     *     array('admin_id'=>'用户id','group_id'=>'用户组id','title'=>'用户组名称','rules'=>'用户组拥有的规则id,多个,号隔开'),
     *     ...)
     */
    protected function getGroups($adminId) {
        static $groups = array();
        if (isset($groups[$adminId]))
            return $groups[$adminId];

        $role2auth = M()
            ->table($this->_config['AUTH_ADMIN_ROLE'] . ' a')
            ->where("a.admin_id='$adminId' and c.status=1")
            ->join($this->_config['AUTH_ROLE_AUTH']." b on a.role_id=b.role_id", "LEFT")
            ->join($this->_config['AUTH_ROLE']." c on a.role_id=c.role_id", "LEFT")
            ->field('b.*')->select();

        $user_roles = array();
        if (!empty($role2auth) && count($role2auth)) {
            foreach ($role2auth as $val) {
                $user_roles[$val['role_id']][] = $val['auth_id'];
            }
        }

        return $user_roles;
    }

    /**
     * 获得权限列表
     * @param integer $adminId  用户id
     */
    public function getAuthList($adminId) {
        static $_authList = array(); //保存用户验证通过的权限列表

        if (isset($_authList[$adminId])) {
            return $_authList[$adminId];
        }
        if ($this->_config['AUTH_TYPE'] == 2 && isset($_SESSION['_AUTH_LIST_' . $adminId])) {
            return $_SESSION['_AUTH_LIST_' . $adminId];
        }

        //免用户组校验
        if (C('ADMINISTRATOR') && in_array($adminId, C('ADMINISTRATOR'))) {
            $map = array();
        }
        //读取用户所属用户组
        else {
            $groups = $this->getGroups($adminId);
            $ids = array();//保存用户所属用户组设置的所有权限规则id
            foreach ($groups as $g) {
                $ids = array_merge($ids, $g);
            }
            $ids = array_unique($ids);
            if (empty($ids)) {
                $_authList[$adminId] = array();
                return array();
            }

            $map = array(
                'auth_id' => array('in',$ids)
            );
        }

        //读取用户组所有权限
        $authList = M()->table($this->_config['AUTH_ACCESS'])->where($map)->select();
        $_authList[$adminId] = $authList;
        if ($this->_config['AUTH_TYPE'] == 2) {
            //规则列表结果保存到session
            $_SESSION['_AUTH_LIST_' . $adminId] = $authList;
        }
        return $authList;
    }

    //获取用户菜单
	public function getMenu($adminId) {
        $menus = array();

        //从缓存中读取
        if ($this->_config['AUTH_TYPE'] == 2 && isset($_SESSION['_MENU_LIST_' . $adminId])) {echo '[session]';
            return $_SESSION['_MENU_LIST_' . $adminId];
        }

        //获取用户需要验证的所有有效规则列表
        $authList = $this->getAuthList($adminId);
        if (empty($authList) || !is_array($authList)) {
            return $menus;
        }

        $menu2auth = array();
        $menuIds = array();
        if (!empty($authList) && count($authList)) {
            foreach ($authList as $auth) {
                $auth['menu_id'] && $menu2auth[$auth['menu_id']] = $auth;
                $auth['menu_id'] && $menuIds[] = $auth['menu_id'];
            }
        }
        $menuIds = array_unique($menuIds);

        //一级菜单
        $topMenus = array();
        $_topMenus = M()->table($this->_config['AUTH_MENU'])
                ->where(array('parent_id'=>0,'status'=>1))
                ->order('sort asc')->select();
        if (!empty($_topMenus) && count($_topMenus)) {
            foreach ($_topMenus as &$val) {
                $topMenus[$val['menu_id']] = $val;
            }
        }

        //子级菜单
        $childMenus = M()->table($this->_config['AUTH_MENU'])
                ->where(array(
                    'menu_id'=>array('in', $menuIds),
                    'status'=>1
                ))
                ->order('sort asc')->select();
        if (!empty($childMenus) && is_array($childMenus)) {
            foreach ($childMenus as $val) {
                if (empty($menus[$val['parent_id']]['child']) || !count($menus[$val['parent_id']]['child'])) {
                    $menus[$val['parent_id']] = $topMenus[$val['parent_id']];
                }
                $menus[$val['parent_id']]['child'][] = $val;
            }
        }

        if ($this->_config['AUTH_TYPE'] == 2) {
            //菜单保存到session
            $_SESSION['_MENU_LIST_' . $adminId] = $menus;
        }

        return $menus;
    }

    //获取所有菜单
    public function getAllMenu(){
        $menus = array();
        $_menus = M()->table($this->_config['AUTH_MENU'])->where()->order('sort asc')->select();

        if (!empty($_menus) && count($_menus)) {
            foreach ($_menus as $val) {
                if ($val['parent_id'] == 0) {
                    $childMenus = isset($menus[$val['menu_id']]['child']) ? $menus[$val['menu_id']]['child'] : array();

                    $menus[$val['menu_id']] = $val;
                    $menus[$val['menu_id']]['child'] = $childMenus;
                } else {
                    $menus[$val['parent_id']]['child'][] = $val;
                }
            }
        }

        return $menus;
    }
    //获取权限控制表模型
    public function getTable($name) {
        return $name ? $this->_config[strtoupper($name)] : '';
    }
}

?>